﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace PFAGame
{
    public class Bourrin : APlayer
    {
        // lvl up
        const float lifeByLvl = 10;
        const float attackSpeedByLvl = 0.9f;
        const float moveSpeedByLvl = 0.3f;
        const float damageByLvl = 2;
        const float resistByLvl = 0.3f;
        const float projectileSpeedByLvl = 1;
        const float critikByLvl = 5;
        const float rangeByLvl = 0.05f;

        bool canAttack = true;
        float timeSinceLastAttack;

        // dash
        public float dashDuration = 0.2f;
        public float dashSpeed;
        public float dashTime = 1000;
        public Vector2 dashDirection;
        List<AMob> mobAlreadyHitByDash;

        static SoundEffect sound;
        SoundEffectInstance soundInstance;

        public override void init()
        {
            base.init();
            playerCLass = e_class.BOURRIN;

            moveRightAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierRunSide2"), 503, 504, 2, (int)(100 / moveSpeed), true);
            moveLeftAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierRunSide"), 503, 504, 2, (int)(100 / moveSpeed), true);
            moveUpAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierRunBack"), 503, 504, 2, (int)(100 / moveSpeed), true);
            moveDownAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierRunFront"), 503, 504, 2, (int)(100 / moveSpeed), true);

            attackRightAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierHitSide2"), 503, 504, 3, (int)(30 * attackSpeed), false);
            attackLeftAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierHitSide"), 503, 504, 3, (int)(30 * attackSpeed), false);
            attackUpAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierHitBack"), 503, 504, 3, (int)(30 * attackSpeed), false);
            attackDownAnim.Initialize(ScreenManager.Singleton.Game.Content.Load<Texture2D>("Images/Mob/Chapelier/ChapelierHitFront"), 503, 504, 3, (int)(30 * attackSpeed), false);

            if (sound == null)
                sound = ScreenManager.Singleton.Game.Content.Load<SoundEffect>("Sound_effects/gun_shot");
            soundInstance = sound.CreateInstance();
            soundInstance.Volume = 0.2f;
            soundInstance.IsLooped = false;
        }

        public override void update(GameTime gameTime)
        {
            base.update(gameTime);
        }

        public override void HandleInput(GameTime gameTime, InputState input)
        {
            // la gestion des déplacements est effectué dans APlayer
            base.HandleInput(gameTime, input);

            PlayerIndex tmpPlayerIndex;

            // attaque
            isAttacking = !canAttack;

            timeSinceLastAttack += ((float)gameTime.ElapsedGameTime.Ticks / 10000000);
            if (timeSinceLastAttack >= attackSpeed / attackSpeedBuffMultiplicator)
                canAttack = true;

            if (canAttack && fire1.Evaluate(input, playerIndex, out tmpPlayerIndex))
            {
                canAttack = false;
                timeSinceLastAttack = 0;

                attackLeftAnim.reset();
                attackDownAnim.reset();
                attackRightAnim.reset();
                attackUpAnim.reset();

                soundInstance.Play();

                List<AObject> mobs = AMob.coneCast(position, orientation, range, angleAttack, GameplayScreen.Singleton.MobList);
                foreach( AMob mob in mobs)
                {
                    Vector2 bumpDirection = mob.Position - position;
                    bumpDirection.Normalize();
                    mob.receiveBump(bumpDirection, 10, 0.1f);
                    mob.receiveDammage(random.Next(100) <= criticalChance ? dammage * criticalMultiplicator * dammageBuffMultiplicator : dammage * dammageBuffMultiplicator);
                }
            }

            if ((canAttack && fire2.Evaluate(input, playerIndex, out tmpPlayerIndex)) || dashTime < dashDuration)
            {
                if (dashTime >= dashDuration) //1ere frame de dash
                {
                    dashDirection = -orientation; // (-) ??
                    dashSpeed = moveSpeed * 3;
                    dashTime = 0;
                    mobAlreadyHitByDash = new List<AMob>();

                    attackLeftAnim.reset();
                    attackDownAnim.reset();
                    attackRightAnim.reset();
                    attackUpAnim.reset();

                    soundInstance.Play();
                }

                canAttack = false;
                timeSinceLastAttack = 0;

                dashTime += ((float)gameTime.ElapsedGameTime.Ticks / 10000000);
                Vector2 tmpPosition;
                //test la colision indépendament sur chaqu'un des axes pour permettre de glisser sur les cases bloquantes
                if (GameplayScreen.Singleton.CurrentType == 1) //on ne peut pas monter en vue de platform
                {
                    tmpPosition = position + dashDirection * dashSpeed * ((float)gameTime.ElapsedGameTime.Ticks / 10000000);
                    tmpPosition.X = position.X;
                    if (!GameplayScreen.Singleton.MapP.checkCollision(tmpPosition))
                        position = tmpPosition;
                }

                tmpPosition = position + dashDirection * dashSpeed * ((float)gameTime.ElapsedGameTime.Ticks / 10000000);
                tmpPosition.Y = position.Y;
                if (!GameplayScreen.Singleton.MapP.checkCollision(tmpPosition))
                    position = tmpPosition;

                List<AObject> mobs = AMob.SphereCast(position, 1f, GameplayScreen.Singleton.MobList);
                foreach (AMob mob in mobs)
                {
                    if (!mobAlreadyHitByDash.Contains(mob))
                    {
                        mobAlreadyHitByDash.Add(mob);
                        Vector2 bumpDirection = mob.Position - position;
                        bumpDirection.Normalize();
                        mob.receiveBump(bumpDirection, 10, 0.1f);
                        mob.receiveDammage(random.Next(100) <= criticalChance ? dammage * criticalMultiplicator * dammageBuffMultiplicator : dammage * dammageBuffMultiplicator);
                    }
                }
            }
        }

        public override void respawn()
        {
            base.respawn();
            dashTime = 1000;
        }

        public override bool upHealth(bool init)
        {
            if (!init && !base.upHealth(false))
                return false;

            maxLife += lifeByLvl;
            life += lifeByLvl;

            return true;
        }

        public override bool upDamage(bool init)
        {
            if (!init && !base.upDamage(false))
                return false;

            dammage += damageByLvl;
            criticalChance += critikByLvl;

            return true;
        }

        public override bool upAttackSpeed(bool init)
        {
            if (!init && !base.upAttackSpeed(false))
                return false;

            attackSpeed *= attackSpeedByLvl;
            range += rangeByLvl;

            attackDownAnim.frameTime = (int)(1000 * attackSpeed);
            attackUpAnim.frameTime = (int)(1000 * attackSpeed);
            attackRightAnim.frameTime = (int)(1000 * attackSpeed);
            attackLeftAnim.frameTime = (int)(1000 * attackSpeed);

            return true;
        }

        public override bool upMoveSpeed(bool init)
        {
            if (!init && !base.upMoveSpeed(false))
                return false;

            moveSpeed += moveSpeedByLvl;
            moveRightAnim.frameTime = (int)(1000 / moveSpeed);
            moveLeftAnim.frameTime = (int)(1000 / moveSpeed);
            moveUpAnim.frameTime = (int)(1000 / moveSpeed);
            moveDownAnim.frameTime = (int)(1000 / moveSpeed);

            return true;
        }

        public override bool upResist(bool init)
        {
            if (!init && !base.upResist(false))
                return false;

            resist += resistByLvl;

            return true;
        }

        internal override string getClass()
        {
            return "Bourrin";
        }
    }
}
